const defaultFields = { key: 'id', parentKey: 'parentId', children: 'children' }

function getReplaceFields(options) {
  return { ...defaultFields, ...options }
}

/**
 * @description 树结构转一维数组
 * @param {Array} treeNode
 * @returns {Array}
 */
export function treeToArray(treeNode) {
  let queen = []
  const out = []
  queen = queen.concat(treeNode)
  while (queen.length) {
    const first = queen.shift()
    const { children, ...item } = first
    if (children) {
      queen = queen.concat(children)
    }
    out.push(item)
  }
  return out
}

/**
 * @description 一维数组转树结构
 * @param {Array} arr
 * @param {Object} replaceFields
 * @returns {Array}
 */
export function arrayToTree(arr, replaceFields = {}) {
  const config = getReplaceFields(replaceFields)
  const { key, parentKey } = config
  const list = arr.filter(item => !item[parentKey])
  const addChildren = (node, dataList) => {
    const children = dataList.filter(item => item[parentKey] === node[key]).map(item => addChildren(item, dataList))
    return { ...node, children }
  }
  return list.map(root => addChildren(root, arr))
}

/**
 * 根据节点id获取树节点
 * @param {Array} treeNode
 * @param {Number} id 节点id
 * @param {Object} replaceFields
 * @returns {Array}
 */
export function getNodeById(treeNode, id, replaceFields = {}) {
  if (!treeNode || !treeNode.length) return
  if (!id && id !== 0) return
  let node
  const config = getReplaceFields(replaceFields)
  const { key, children } = config
  function fn(treeNode, nodeId) {
    for (let i = 0; i < treeNode.length; i += 1) {
      const item = treeNode[i]
      // eslint-disable-next-line
      if (item[key] == nodeId) {
        node = item
        break
      } else {
        const child = item[children]
        if (child && child.length > 0) {
          fn(child, nodeId)
        }
      }
    }
  }
  fn(treeNode, id)
  return node
}

/**
 * @description 根据节点id获取所有父级节点
 * @param {Array} treeNode 树
 * @param {Number} id 节点id
 * @param {Object} replaceFields
 * @returns {Array}
 */
export function getAllParentNodeById(treeNode, id, replaceFields = {}) {
  if (!id && id !== 0) return []
  const config = getReplaceFields(replaceFields)
  const { parentKey } = config
  const parents = []
  function fn(nodeId) {
    const node = getNodeById(treeNode, nodeId, config)
    if (node) {
      parents.unshift(node)
      if (node[parentKey]) {
        fn(node[parentKey])
      }
    }
  }
  fn(id)
  return parents
}

/**
 * @description	过滤节点，返回新的树
 * @param {Array} treeNode
 * @param {Function} callback 函数接收树节点作为参数,
 * 返回true将过滤该节点
 * @return	{Array}
 */
export function filterNodes(treeNode, callback, replaceFields = {}) {
  if (!treeNode || !treeNode.length) return
  const config = getReplaceFields(replaceFields)
  const { children } = config
  function fn(treeNode, parentNode) {
    for (let i = 0; i < treeNode.length; i++) {
      const item = treeNode[i]
      if (typeof callback === 'function' && callback(item)) {
        parentNode ? parentNode[children].splice(i, 1) : treeNode.splice(i, 1)
      }
      const child = item[children]
      if (child && child.length > 0) {
        fn(child, item)
      }
    }
  }
  fn(treeNode)
  return treeNode
}
